package com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.properties;

import com.intellij.openapi.application.ReadAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.psi.PsiType;
import com.intellij.ui.JBColor;
import com.neuronbit.businessflow.intellij.dialog.TaskReturnFiledValueAssignToFlowReturnFieldTreeDialog;
import com.neuronbit.businessflow.intellij.editor.UIDesignerBundle;
import com.neuronbit.businessflow.intellij.editor.swing.editor.RadComponent;
import com.neuronbit.businessflow.intellij.editor.swing.editor.RadJavaMethodComponent;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.InplaceContext;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.Property;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.PropertyEditor;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.PropertyRenderer;
import com.neuronbit.businessflow.intellij.editor.swing.editor.propertyInspector.renderers.LabelPropertyRenderer;
import com.neuronbit.businessflow.intellij.model.ParamValue;
import com.neuronbit.businessflow.intellij.model.Return;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Set;

/**
 * The type Field 2 property.
 */
public class TaskReturnTypeFieldProperty extends Property<RadJavaMethodComponent, String> {
    private final Project project;
    private final PsiType fieldType;
    private final PsiType returnType;
    private final PropertyRenderer myRenderer;
    private final PropertyEditor myEditor = new MyPropertyEditor();
    private final String fieldName;

    /**
     * Instantiates a new Field 2 property.
     *
     * @param parent     the parent
     * @param project    the project
     * @param fieldName  the field name
     * @param fieldType  the field type
     * @param returnType the return type
     */
    public TaskReturnTypeFieldProperty(@NotNull Property parent, Project project, @NotNull String fieldName, @NotNull PsiType fieldType, PsiType returnType) {
        super(parent, fieldName + ":" + ReadAction.compute(fieldType::getPresentableText));
        this.project = project;
        this.fieldType = fieldType;
        this.returnType = returnType;
        this.myRenderer = new LabelPropertyRenderer();
        this.fieldName = fieldName;
    }

    @Override
    public @NotNull PropertyRenderer<String> getRenderer() {
        return myRenderer;
    }

    @Override
    public @Nullable PropertyEditor<String> getEditor() {
        return myEditor;
    }

    @Override
    public String getValue(RadJavaMethodComponent component) {
        Set<Return> returns = component.getFlowReturns();
        if (null == returns) {
            return "";
        }
        for (Return aReturn : returns) {
            if (aReturn.getValues() == null) {
                continue;
            }
            for (ParamValue paramValue : aReturn.getValues()) {
                if (paramValue == null) {
                    continue;
                }
                //TODO shunyun 2024/4/16: 多级就比较难处理
                if ((component.getName() + ("output".equals(fieldName) ? "." : ".output.") + fieldName).equals(paramValue.getValue())) {
                    return aReturn.getName();
                }
            }
        }

        return "";
    }

    @Override
    protected void setValueImpl(RadJavaMethodComponent component, String value) throws Exception {
        component.setFlowReturnValue(component.getName(), this.fieldName, value);
    }
//
//    @Override
//    public Property @NotNull [] getChildren(RadJavaMethodComponent component) {
//        return new Property[]{
//                new FieldNameProperty(this, component.getProject(), this.fieldName),
//                new FieldClassToBindProperty(this, component.getProject(), this.fieldType, "type"),
//                new FieldValueToAssignProperty(this, component.getProject(), this.fieldName, this.fieldType, returnType, "return as")
//        };
//    }

    @Override
    public boolean needRefreshPropertyList() {
        return true;
    }

    private class MyPropertyEditor extends PropertyEditor {
        private final TextFieldWithBrowseButton myTf = new TextFieldWithBrowseButton();
        private RadComponent component;

        /**
         * Instantiates a new My property editor.
         */
        MyPropertyEditor() {
            //myTf.setText(UIDesignerBundle.message("client.properties.configure"));
            myTf.getTextField().setEditable(false);
            myTf.getTextField().setBorder(null);
            myTf.getTextField().setForeground(JBColor.foreground());
            myTf.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    showClientPropertiesDialog();
                }
            });
        }

        private void showClientPropertiesDialog() {
            TaskReturnFiledValueAssignToFlowReturnFieldTreeDialog dialog = new TaskReturnFiledValueAssignToFlowReturnFieldTreeDialog(project,
                    returnType,
                    fieldName,
                    fieldType);
            if (dialog.showAndGet()) {
                String result = dialog.getSelected();
                if (result != null) {
                    myTf.setText(result);
                }
            }
//            ConfigureClientPropertiesDialog dlg = new ConfigureClientPropertiesDialog(myProject);
//            dlg.show();
//            if (dlg.getExitCode() == DialogWrapper.OK_EXIT_CODE) {
//                dlg.save();
//                fireValueCommitted(true, false);
//            }
        }

        @Override
        public Object getValue() throws Exception {
            final String value = myTf.getText();
            return value.replace('$', '.'); // PSI works only with dots
        }

        @Override
        public JComponent getComponent(final RadComponent component, final Object value, final InplaceContext inplaceContext) {
            this.component = component;
            if (null != value) {
                myTf.setText(value.toString());
            } else {
                myTf.setText(UIDesignerBundle.message("client.properties.configure"));
            }
            return myTf;
        }

        @Override
        public void updateUI() {
            SwingUtilities.updateComponentTreeUI(myTf);
        }
    }
}
